#include "stdafx.h"
#include "Extensions.h"

namespace AppliedCryptography
{
	ASN1ObjectIdentifier Extensions::BasicConstraintsOID("2.5.29.19");

	Extensions::Extensions(ClassBits classBits, ConstructedBit constucted, TypeNumberBits number)
		: ASN1Encodable(classBits, constucted, number)
	{
	};

	Extensions::Extensions()
		: ASN1Encodable(ContextSpec, Constructed, Explicit03)
	{
	};

	Extensions::Extensions(Extensions& other)
		: ASN1Encodable(ContextSpec, Constructed, Explicit03)
	{
		ASN1Sequence* seq = NULL;

		for(unsigned int i=0; i<other.size(); i++)
		{
			ASN1ObjectIdentifier extnid = other.getExtensionOID(i);
			ASN1Bool critical = other.getExtensionCritical(i);
			ASN1OctectString extnValue = other.getExtensionValue(i);

			seq = new ASN1Sequence();

			seq->add(extnid);
			seq->add(critical);
			seq->add(extnValue);

			_value.add(*seq);
			_extensions.push_back(seq);
		};
	};

	Extensions::~Extensions()
	{
		this->flush();
	};

	Extensions& Extensions::add(ASN1ObjectIdentifier& extnid, ASN1Bool& critical, ASN1OctectString& extnValue)
	{
		ASN1Sequence* extension = new ASN1Sequence();
		extension->add(extnid);
		extension->add(critical);
		extension->add(extnValue);

		_value.add(*extension);
		_extensions.push_back(extension);
		return *this;
	};

	ASN1ObjectIdentifier& Extensions::getExtensionOID(unsigned int index) const
	{
		ASN1Sequence* seq = (ASN1Sequence*)&_value.get(index);
		return *(ASN1ObjectIdentifier*)&(seq->get(0));
	};

	ASN1Bool& Extensions::getExtensionCritical(unsigned int index) const
	{
		ASN1Sequence* seq = (ASN1Sequence*)&_value.get(index);
		return *(ASN1Bool*)&(seq->get(1));
	};

	ASN1OctectString& Extensions::getExtensionValue(unsigned int index) const
	{
		ASN1Sequence* seq = (ASN1Sequence*)&_value.get(index);
		return *(ASN1OctectString*)&(seq->get(2));
	};

	Extensions& Extensions::flush()
	{
		for(unsigned int i=0; i<_extensions.size(); i++)
		{
			delete _extensions[i];
		};
		_extensions.clear();

		return *this;
	};

	unsigned int Extensions::size() const
	{
		return _value.size();
	};

	std::vector<byte> Extensions::getContentBits() const
	{
		return _value.encode();
	};

	Extensions& Extensions::operator=(const Extensions& other)
	{
		ASN1Sequence* seq = NULL;

		this->flush();

		for(unsigned int i=0; i<other.size(); i++)
		{
			ASN1ObjectIdentifier& extnid = other.getExtensionOID(i);
			ASN1Bool& critical = other.getExtensionCritical(i);
			ASN1OctectString& extnValue = other.getExtensionValue(i);

			seq = new ASN1Sequence();

			seq->add(extnid);
			seq->add(critical);
			seq->add(extnValue);

			_value.add(*seq);
			_extensions.push_back(seq);
		};

		return *this;
	};
}; // namespace AppliedCryptography
